/**
 * @file       godemool/sprop.h
 * @brief      send property class.
 * @author     ben "boin" bonoeil
 * @date       2015-02
 */

/* Copyright (c) 2007-2015, ben "boin" bonoeil */

#ifndef GODEMOOL_SPROP_H
#define GODEMOOL_SPROP_H

#include "godemool/types.h"
#include "godemool/strpool.h"

namespace boin {
  
  // Maximum length of a string that can be sent.
  enum {
    DT_MAX_STRING_BITS = 9,
    DT_MAX_STRING_BUFFERSIZE = 1<<DT_MAX_STRING_BITS
  };

  struct SProp {
    /** send properties value types. */
    enum Type {
      Int32, Float, V3d, V2d, Str, Array, DataTable, Int64, Last
    };

  SProp() : type(Last) {}
  SProp(Type t) : type(t) {};
  SProp(int32_t val) : type(Int32), value(val) {}
  SProp(int64_t val) : type(Int64), value(val) {}
  SProp(float val) : type(Float), value(val) {}
  SProp(wetstring val) : type(Str), value(val) {}

    /** send properties flags. */
    enum Flags {
      UNSIGNED				= ( 1 << 0 ),	// Unsigned integer data.
      COORD					= ( 1 << 1 ),	// If this is set, the float/vector is treated like a world coordinate. Note that the bit count is ignored in this case.
      NOSCALE				= ( 1 << 2 ),	// For floating point, don't scale into range, just take value as is.
      ROUNDDOWN				= ( 1 << 3 ),	// For floating point, limit high value to range minus one bit unit
      ROUNDUP				= ( 1 << 4 ),	// For floating point, limit low value to range minus one bit unit
      NORMAL				= ( 1 << 5 ),	// If this is set, the vector is treated like a normal = (only valid for vectors),
      EXCLUDE				= ( 1 << 6 ),	// This is an exclude prop = (not excludED, but it points at another prop to be excluded),.
      XYZE					= ( 1 << 7 ),	// Use XYZ/Exponent encoding for vectors.
      INSIDEARRAY			= ( 1 << 8 ),	// This tells us that the property is inside an array, so it shouldn't be put into the flattened property list. Its array will point at it when it needs to.
      PROXY_ALWAYS_YES		= ( 1 << 9 ),	// Set for datatable props using one of the default datatable proxies like SendProxy_DataTableToDataTable that always send the data to all clients.
      IS_A_VECTOR_ELEM		= ( 1 << 10 ),	// Set automatically if SPROP_VECTORELEM is used.
      COLLAPSIBLE			= ( 1 << 11 ),	// Set automatically if it's a datatable with an offset of 0 that doesn't change the pointer = (ie: for all automatically-chained base classes),.
      COORD_MP				= ( 1 << 12 ), // Like SPROP_COORD, but special handling for multiplayer games
      COORD_MP_LOWPRECISION = ( 1 << 13 ), // Like SPROP_COORD, but special handling for multiplayer games where the fractional component only gets a 3 bits instead of 5
      COORD_MP_INTEGRAL		= ( 1 << 14 ), // SPROP_COORD_MP, but coordinates are rounded to integral boundaries
      CELL_COORD			= ( 1 << 15 ), // Like SPROP_COORD, but special encoding for cell coordinates that can't be negative, bit count indicate maximum value
      CELL_COORD_LOWPRECISION = ( 1 << 16 ), // Like SPROP_CELL_COORD, but special handling where the fractional component only gets a 3 bits instead of 5
      CELL_COORD_INTEGRAL	= ( 1 << 17 ), // SPROP_CELL_COORD, but coordinates are rounded to integral boundaries
      CHANGES_OFTEN			= ( 1 << 18 ),	// this is an often changed field, moved to head of sendtable so it gets a small index
      VARINT				= ( 1 << 19 ),	// use var int encoded = (google protobuf style),, note you want to include SPROP_UNSIGNED if needed, its more efficient
    };


    struct Value {
      Value();
      Value(int32_t val) { i32 = val; }
      Value(int64_t val) { i64 = val; }
      Value(float val) { fp = val; }
      Value(wetstring val) { str = val; }
      Value(const Vector & val) { vec.x = val.x; vec.x = val.y; vec.x = val.z; }
      Value(const std::string & val);

      union {
        int32_t i32;
        float fp;
        wetstring str;
        int64_t i64;
        struct { float x,y,z; } vec;
      };
    };

    Type type;
    Value value;

    //	int m_nNumElements;
  };

}
// struct FlattenedPropEntry;
// Prop_t *DecodeProp( CBitRead &entityBitBuffer, FlattenedPropEntry *pFlattenedProp, uint32 uClass, int nFieldIndex, bool bQuiet );

#endif
